package com.crrc.sandameter

import android.annotation.SuppressLint
import android.Manifest
import android.app.Activity
import android.bluetooth.*
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.ParcelUuid
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import com.cj.mvvmlib.base.activity.BaseVmActivity
import com.cj.mvvmlib.util.ToastUtil
import com.crrc.sandameter.databinding.ActivityMainBinding
import com.crrc.sandameter.http.isNetConnected
import java.util.Arrays
import java.util.UUID

// 体重秤服务 (Weight Scale Service)
private const val WEIGHT_SCALE_SERVICE_UUID_STRING = "0000181D-0000-1000-8000-00805f9b34fb"

// 体重测量特征 (Weight Measurement Characteristic)
private const val WEIGHT_MEASUREMENT_CHARACTERISTIC_UUID_STRING =
    "00002A9D-0000-1000-8000-00805f9b34fb"

// CCCD (Client Characteristic Configuration Descriptor) UUID，用于启用通知/指示
private const val CCCD_UUID_STRING = "00002902-0000-1000-8000-00805f9b34fb"

class MainActivity : BaseVmActivity<MainViewModel>() {
    private lateinit var bluetoothManager: BluetoothManager
    private var bluetoothAdapter: BluetoothAdapter? = null
    private var bluetoothLeScanner = bluetoothAdapter?.bluetoothLeScanner
    private var bluetoothGatt: BluetoothGatt? = null

    private var targetDevice: BluetoothDevice? = null
    private var weightCharacteristic: BluetoothGattCharacteristic? = null

    private val handler = Handler(Looper.getMainLooper())
    private var isScanning = false
    private var isConnected = false
    private lateinit var mainBinding: ActivityMainBinding
    override fun useTitleBar(): Boolean {
        return false
    }

    override fun layoutId(): View {
        mainBinding = ActivityMainBinding.inflate(layoutInflater)
        return mainBinding.root
    }

    // 目标设备名称 (可选，用于过滤扫描结果)
    private val TARGET_DEVICE_NAME = "Your_Scale_Name" // TODO: 替换为您的电子秤蓝牙名称，或留空

    companion object {
        private const val TAG = "BleScaleDemo"
        private const val REQUEST_ENABLE_BT = 1
        private const val SCAN_PERIOD: Long = 10000 // 扫描持续时间10秒
    }

    // 权限请求 Launcher
    private val requestPermissionsLauncher =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
            var allGranted = true
            permissions.entries.forEach {
                if (!it.value) {
                    allGranted = false
                    Log.w(TAG, "权限 ${it.key} 未被授予")
                }
            }
            if (allGranted) {
                Log.i(TAG, "所有必须权限已被授予")
                initializeBluetooth()
            } else {
                Toast.makeText(this, "需要蓝牙和位置权限才能使用此功能", Toast.LENGTH_LONG).show()
                ToastUtil.showShortToast("权限不足")
            }
        }

    override fun initView(savedInstanceState: Bundle?) {
        mainBinding.text2.text = "你好，世界"
    }

    override fun initData() {
    }

    override fun setListener() {
        mainBinding.netCheck.setOnClickListener {
            if (isNetConnected()) {
                ToastUtil.showShortToast("网络已连接")
            } else {
                ToastUtil.showShortToast("网络未连接")
            }
            val positiveData = byteArrayOf(0x35, 0x34, 0x2e, 0x33, 0x32, 0x30, 0x30, 0x3d)
            val weight1 = viewModel.parseWeightData(positiveData)
            mainBinding.text2.text = "$weight1"
        }
    }

    override fun createObserver() {
    }

    private fun checkAndRequestPermissions() {
        val requiredPermissions = mutableListOf<String>()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12+
            requiredPermissions.add(Manifest.permission.BLUETOOTH_SCAN)
            requiredPermissions.add(Manifest.permission.BLUETOOTH_CONNECT)
        } else {
            requiredPermissions.add(Manifest.permission.BLUETOOTH)
            requiredPermissions.add(Manifest.permission.BLUETOOTH_ADMIN)
            requiredPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION) // Android 6-11 需要
        }

        val permissionsToRequest = requiredPermissions.filter {
            ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
        }

        if (permissionsToRequest.isNotEmpty()) {
            requestPermissionsLauncher.launch(permissionsToRequest.toTypedArray())
        } else {
            Log.i(TAG, "所有权限已授予，正在初始化蓝牙...")
            initializeBluetooth()
        }
    }


    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun initializeBluetooth() {
        bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        bluetoothAdapter = bluetoothManager.adapter

        if (bluetoothAdapter == null) {
            ToastUtil.showShortToast("此设备不支持蓝牙")
            Toast.makeText(this, "此设备不支持蓝牙", Toast.LENGTH_SHORT).show()
            finish()
            return
        }

        if (!bluetoothAdapter!!.isEnabled) {
            val enableBtIntent =
                Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) // 使用新的 ActivityResultLauncher 启动蓝牙
            activityResultLauncher.launch(enableBtIntent)
        } else {
            bluetoothLeScanner = bluetoothAdapter?.bluetoothLeScanner
            ToastUtil.showShortToast("蓝牙已就绪")
        }
    }

    // 处理蓝牙启用请求的结果
    private val activityResultLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                Log.i(TAG, "蓝牙已成功启用")
                bluetoothLeScanner = bluetoothAdapter?.bluetoothLeScanner
                ToastUtil.showShortToast("蓝牙已启用")
            } else {
                Log.w(TAG, "用户未启用蓝牙")
                ToastUtil.showShortToast("蓝牙未启用")
                Toast.makeText(this, "需要启用蓝牙才能扫描设备", Toast.LENGTH_LONG).show()
            }
        }


    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun checkPermissionsAndScan() { // 再次确认权限，以防万一
        val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT)
        } else {
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN)
        }

        val allPermissionsGranted = requiredPermissions.all {
            ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
        }

        if (!allPermissionsGranted) {
            Toast.makeText(this, "缺少必要的蓝牙或位置权限", Toast.LENGTH_SHORT).show()
            checkAndRequestPermissions() // 重新请求
            return
        }
        if (bluetoothAdapter?.isEnabled == true) {
            startScan()
        } else {
            Toast.makeText(this, "请先启用蓝牙", Toast.LENGTH_SHORT).show()
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            activityResultLauncher.launch(enableBtIntent)
        }
    }

    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun startScan() {
        if (isScanning) return
        targetDevice = null // 重置目标设备
        //        connectButton.isEnabled = false

        val filters = mutableListOf<ScanFilter>() // 按服务 UUID 过滤 (推荐)
        val serviceUuid = ParcelUuid.fromString(WEIGHT_SCALE_SERVICE_UUID_STRING)
        filters.add(ScanFilter.Builder().setServiceUuid(serviceUuid).build())

        // 或者按设备名称过滤 (如果名称固定且已知)
        // if (TARGET_DEVICE_NAME.isNotBlank()) {
        //     filters.add(ScanFilter.Builder().setDeviceName(TARGET_DEVICE_NAME).build())
        // }


        val settings =
            ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // 高频扫描，如果需要快速发现
                .build()

        bluetoothLeScanner?.startScan(filters, settings, leScanCallback)
        isScanning = true

        //        scanButton.text = "停止扫描"
        ToastUtil.showShortToast("扫描中...")
        Log.i(TAG, "开始扫描 BLE 设备...")

        // 预设时间后停止扫描，防止无限扫描消耗电量
        handler.postDelayed({
            if (isScanning) {
                stopScan()
                if (targetDevice == null) {
                    ToastUtil.showShortToast("未找到目标电子秤")
                    Log.i(TAG, "扫描结束，未找到设备")
                }
            }
        }, SCAN_PERIOD)
    }

    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun stopScan() {
        if (!isScanning) return
        bluetoothLeScanner?.stopScan(leScanCallback)
        isScanning = false
        ToastUtil.showShortToast("开始扫描")
        if (targetDevice == null) { // 只有在确实没找到设备时才更新状态
            ToastUtil.showShortToast("扫描已停止")
        }
        Log.i(TAG, "停止扫描 BLE 设备")
    }

    private val leScanCallback = object : ScanCallback() {
        @SuppressLint("MissingPermission") // 权限已在调用前检查
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            super.onScanResult(callbackType, result)
            Log.i(TAG,
                "扫描到设备: ${result.device.name ?: "Unknown Device"} (${result.device.address}) RSSI: ${result.rssi}")

            // 检查设备名称或服务UUID是否匹配 (如果ScanFilter不够用)
            // 这里我们假设ScanFilter已经处理了服务UUID的匹配
            // 如果需要更复杂的逻辑，可以在这里添加
            // 例如：if (result.device.name == TARGET_DEVICE_NAME) { ... }

            // 找到目标服务UUID的设备后，可以认为它是目标设备
            // 或者，如果你的秤有特定的广播名称，也可以用那个来判断
            if (result.scanRecord?.serviceUuids?.contains(ParcelUuid.fromString(
                    WEIGHT_SCALE_SERVICE_UUID_STRING)) == true || (TARGET_DEVICE_NAME.isNotBlank() && result.device.name == TARGET_DEVICE_NAME)) {
                targetDevice =
                    result.device //                statusTextView.text = "找到设备: ${targetDevice?.name ?: targetDevice?.address}"
                //                connectButton.isEnabled = true
                Log.i(TAG, "找到目标电子秤: ${targetDevice?.address}")
                stopScan() // 找到后立即停止扫描
            }
        }

        override fun onBatchScanResults(results: List<ScanResult>) {
            super.onBatchScanResults(results)
            Log.d(TAG, "批量扫描结果: ${results.size}")
        }

        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
            Log.e(TAG, "扫描失败，错误码: $errorCode")
            ToastUtil.showShortToast("扫描失败")
            isScanning = false //            scanButton.text = "开始扫描"
        }
    }

    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun connectToDevice(device: BluetoothDevice) {
        if (isConnected) {
            Log.w(TAG, "已连接，无需重复连接")
            return
        }
        ToastUtil.showShortToast("连接中: ${device.name ?: device.address}")
        Log.i(TAG,
            "尝试连接到设备: ${device.address}") // autoConnect 参数为 false 表示直接连接，true 表示当设备再次可用时自动连接（后台）
        // 对于需要稳定连接的场景，首次连接用 false，后续断线重连可以考虑 true，但 true 的行为在不同设备上可能不一致
        bluetoothGatt = device.connectGatt(this, false, gattCallback)
    }

    private val gattCallback = object : BluetoothGattCallback() {
        @SuppressLint("MissingPermission") // 权限已在调用前检查
        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            val deviceAddress = gatt.device.address
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    isConnected = true
                    Log.i(TAG, "成功连接到 $deviceAddress")
                    runOnUiThread {
                        ToastUtil.showShortToast("已连接: ${gatt.device.name ?: deviceAddress}") //                        connectButton.isEnabled = false
                        //                        disconnectButton.isEnabled = true
                    } // 连接成功后，发现服务
                    handler.postDelayed({ // 稍作延迟，确保连接稳定
                        bluetoothGatt?.discoverServices()
                    }, 500)

                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    isConnected = false
                    Log.i(TAG, "与 $deviceAddress 断开连接")
                    runOnUiThread {
                        ToastUtil.showShortToast("已断开") //                        weightTextView.text = "体重: --"
                        //                        connectButton.isEnabled = targetDevice != null // 如果有目标设备，允许重连
                        //                        disconnectButton.isEnabled = false
                    }
                    closeGatt() // 清理资源
                    // TODO: 在这里实现重连逻辑，例如延迟后尝试 connectToDevice(gatt.device)
                    // handleReconnect(gatt.device)
                }
            } else { // 连接失败或发生错误
                isConnected = false
                Log.e(TAG,
                    "连接状态改变错误 for $deviceAddress, status: $status, newState: $newState")
                runOnUiThread {
                    ToastUtil.showShortToast("连接失败 (错误码: $status)") //                    weightTextView.text = "体重: --"
                    //                    connectButton.isEnabled = targetDevice != null
                    //                    disconnectButton.isEnabled = false
                }
                closeGatt() // TODO: 实现重连逻辑或错误处理
                // handleReconnect(gatt.device)
            }
        }

        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.i(TAG, "服务发现成功")
                runOnUiThread {
                    ToastUtil.showShortToast("服务已发现")
                }

                val serviceUuid = UUID.fromString(WEIGHT_SCALE_SERVICE_UUID_STRING)
                val characteristicUuid =
                    UUID.fromString(WEIGHT_MEASUREMENT_CHARACTERISTIC_UUID_STRING)

                val service = gatt.getService(serviceUuid)
                if (service == null) {
                    Log.e(TAG, "未找到体重秤服务 UUID: $serviceUuid")
                    runOnUiThread {
                        ToastUtil.showShortToast("未找到体重秤服务")
                    }
                    disconnectDevice() // 服务不匹配，断开连接
                    return
                }

                weightCharacteristic = service.getCharacteristic(characteristicUuid)
                if (weightCharacteristic == null) {
                    Log.e(TAG, "未找到体重测量特征 UUID: $characteristicUuid")
                    runOnUiThread {
                        ToastUtil.showShortToast("未找到体重测量特征")
                    }
                    disconnectDevice()
                    return
                }

                // 启用特征通知
                enableNotifications(gatt, weightCharacteristic!!)

            } else {
                Log.w(TAG, "服务发现失败: $status")
                runOnUiThread {
                    ToastUtil.showShortToast("服务发现失败")
                }
                disconnectDevice()
            }
        }

        @SuppressLint("MissingPermission") // 权限已在调用前检查
        private fun enableNotifications(gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic) { // 检查特征是否支持通知或指示
            if ((characteristic.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0 && (characteristic.properties and BluetoothGattCharacteristic.PROPERTY_INDICATE) == 0) {
                Log.e(TAG, "特征不支持通知或指示")
                runOnUiThread {
                    ToastUtil.showShortToast("特征不支持通知")
                }
                return
            }

            // 启用本地通知
            if (!gatt.setCharacteristicNotification(characteristic, true)) {
                Log.e(TAG, "启用特征 ${characteristic.uuid} 通知失败")
                runOnUiThread {
                    ToastUtil.showShortToast("启用通知失败(1)")
                }
                return
            }

            // 获取 CCCD (Client Characteristic Configuration Descriptor)
            val cccdUuid = UUID.fromString(CCCD_UUID_STRING)
            val descriptor = characteristic.getDescriptor(cccdUuid)
            if (descriptor == null) {
                Log.e(TAG,
                    "未找到特征 ${characteristic.uuid} 的 CCCD (UUID: $cccdUuid)") // 某些设备可能不需要显式写入CCCD，如果setCharacteristicNotification(true)后能收到数据，这里可以忽略
                // 但标准做法是需要写入的
                runOnUiThread {
                    ToastUtil.showShortToast("启用通知失败(CCCD缺失)")
                } // 如果这里失败，但设备依然能发送数据，可能是因为某些设备在setCharacteristicNotification(true)时自动处理了
                // 但为了兼容性，最好还是写入CCCD
                return
            }

            // 根据特征属性选择启用 NOTIFY 或 INDICATE
            val payload =
                if ((characteristic.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                } else if ((characteristic.properties and BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
                    BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
                } else {
                    Log.e(TAG, "特征 ${characteristic.uuid} 既不支持 NOTIFY 也不支持 INDICATE")
                    return
                }

            descriptor.value = payload
            if (!gatt.writeDescriptor(descriptor)) {
                Log.e(TAG, "写入 CCCD 失败 for ${characteristic.uuid}")
                runOnUiThread {
                    ToastUtil.showShortToast("启用通知失败(CCCD写入)")
                }
            } else {
                Log.i(TAG, "成功请求启用 ${characteristic.uuid} 的通知/指示")
                runOnUiThread {
                    ToastUtil.showShortToast("等待数据...")
                }
            }
        }


        // 当成功写入 Descriptor (如 CCCD) 后回调
        override fun onDescriptorWrite(gatt: BluetoothGatt,
            descriptor: BluetoothGattDescriptor,
            status: Int) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (descriptor.uuid == UUID.fromString(CCCD_UUID_STRING)) {
                    if (Arrays.equals(descriptor.value,
                            BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) || Arrays.equals(
                            descriptor.value,
                            BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)) {
                        Log.i(TAG, "成功启用特征 ${descriptor.characteristic.uuid} 的通知/指示")
                        runOnUiThread {
                            ToastUtil.showShortToast("通知已启用, 等待数据...")
                        }
                    } else if (Arrays.equals(descriptor.value,
                            BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)) {
                        Log.i(TAG, "成功禁用特征 ${descriptor.characteristic.uuid} 的通知/指示")
                    }
                }
            } else {
                Log.e(TAG, "写入 Descriptor ${descriptor.uuid} 失败, status: $status")
                runOnUiThread {
                    ToastUtil.showShortToast("配置通知失败 (错误码: $status)")
                }
            }
        }

        // 当特征值改变时回调 (接收到数据)
        override fun onCharacteristicChanged(gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic) {
            if (characteristic.uuid == weightCharacteristic?.uuid) {
                val data = characteristic.value
                Log.i(TAG,
                    "收到数据来自 ${characteristic.uuid}: ${data.toHexString()}") // !!! 解析数据 !!!
                // 电子秤的数据格式各不相同，需要参考其文档
                // 例如，一个简单的情况可能是直接发送体重的浮点数或整数
                // 这里仅作演示，具体解析逻辑需要替换
                viewModel.parseWeightData(data)
            }
        }

        override fun onCharacteristicRead(gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            status: Int) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.i(TAG,
                    "读取特征 ${characteristic.uuid} 成功: ${characteristic.value.toHexString()}")
                if (characteristic.uuid == weightCharacteristic?.uuid) {
                    viewModel.parseWeightData(characteristic.value)
                }
            } else {
                Log.e(TAG, "读取特征 ${characteristic.uuid} 失败, status: $status")
            }
        }
    }

    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun disconnectDevice() {
        if (bluetoothGatt == null) {
            return
        }
        Log.i(TAG, "请求断开连接...")
        bluetoothGatt?.disconnect() // closeGatt() 会在 onConnectionStateChange 的 STATE_DISCONNECTED 中调用
    }

    @SuppressLint("MissingPermission") // 权限已在调用前检查
    private fun closeGatt() {
        bluetoothGatt?.close()
        bluetoothGatt = null
        isConnected = false
        weightCharacteristic = null
        Log.i(TAG, "GATT 连接已关闭并释放资源")
        runOnUiThread {
//            connectButton.isEnabled = targetDevice != null
//            disconnectButton.isEnabled = false
//            if (statusTextView.text.toString()
//                    .startsWith("已连接") || statusTextView.text.toString().startsWith("连接中")) {
//                statusTextView.text = "已断开"
//            }
//            weightTextView.text = "体重: --"
        }
    }

    // 字节数组转十六进制字符串，方便日志查看
    fun ByteArray.toHexString(): String =
        joinToString(separator = " ", prefix = "0x") { String.format("%02X", it) }


    override fun onDestroy() {
        super.onDestroy()
        Log.i(TAG, "Activity onDestroy, 清理资源")
        stopScan() // 确保停止扫描
        disconnectDevice() // 断开连接并释放GATT资源
        // 如果使用了 Service，在这里解绑或停止 Service
    }
}